IoT Coreで受け取ったデータをCloudWatchで状態監視してみた

IoT Coreで受け取ったデータをCloudWatchで状態監視してみた

Clock Icon2024.09.07

はじめに

IoT Coreで受け取った測定データが特定のしきい値を超えた場合に通知を受け取りたいことってありますよね??
また、実際に機器を扱う現場ではアラートが出た後、しきい値を下回った場合にも通知を受け取りたいということも多いと思います。
今回は受け取ったデータを可視化サービスで通知設定したり、lambdaで加工したり、DBに保存してなんやかんやしなくても、IoT CoreとCloudWatchを使って上記の仕組みを簡単に作る方法をご紹介します。

やりたいことをイラストにするとこんな感じです。
image20

しきい値を超えた場合に通知を受け、正常に戻った場合も通知を受けとります。

条件

今回は以下の条件で通知を行いたいと思います。

  • 値が30.0を超えたらアラート通知
  • ステータスがアラート状態から正常に回復した場合に回復通知

しきい値は整数しか設定できません。
そのため小数点以下の精度で判断が必要な場合は別のソリューションが必要です。

全体図

まずは全体のアーキテクチャです。
image2

設定の流れをざっくりまとめるとこんな感じです。

  1. IoT Coreでデータ受け取る
  2. IoT CoreのルールでCloudWatchのカスタムメトリクスに転送する
  3. CloudWatchアラームでしきい値ベースのアラームを設定する(同時に解除通知も設定)

それでは実際に作っていきましょう。
今回は再現性を高くするためにAWS CLIで作成していきます。

IAM

まずはIoTルールに必要なロールとポリシーを作成します。

値は適宜読み替えてください。

aws iam create-role \
  --role-name demo-role-iot-rule-alart \
  --assume-role-policy-document \
'{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "iot.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}'

インラインポリシー

aws iam put-role-policy \
  --role-name demo-role-iot-rule-alart \
  --policy-name demo-inline-policy-iot-rule-alart \
  --policy-document \
'{
    "Version": "2012-10-17",
    "Statement": 
        {
            "Effect": "Allow",
            "Action": "cloudwatch:PutMetricData",
            "Resource": "*"
        }
}'

ここで作成したロールは次のIoTルールで使用します。
内容は機器から受け取ったデータをCloudWatchにPutするための権限です。

IoT Core

IoT Coreで受け取ったデータをCloudWatchへ転送するルールを作成します。
image3

こちらのルールでは osaka/factory_a/thermometer/demo-device というトピックに入ったデータの temp の値をCloudWatchに送信します。
ロールARNは先ほど作成したロールのARNです。

以下のパラメータで作成します。

項目
ルール名 demo_iot_rule_temp_monitor
SQL SELECT temp FROM 'osaka/factory_a/thermometer/demo-device'
アクション CloudWatchメトリクスへ送信
メトリクス名 temp
メトリクス名前空間 IoT/Device
メトリクス値 ${temp}
メトリクス単位 None
ロールARN arn:aws:iam::<account-id>:role/demo-role-iot-rule-alart
aws iot create-topic-rule \
    --region ap-northeast-1 \
    --rule-name "demo_iot_rule_temp_monitor" \
    --topic-rule-payload '{
        "awsIotSqlVersion": "2016-03-23",
        "sql": "SELECT temp FROM '\''osaka/factory_a/thermometer/demo-device'\''",
        "description": "Rule to send temperature to CloudWatch metrics",
        "actions": [{
            "cloudwatchMetric": {
                "metricName": "temp",
                "metricNamespace": "IoT/Device",
                "metricValue": "${temp}",
                "metricUnit": "None",
                "roleArn": "arn:aws:iam::<account-id>:role/demo-role-iot-rule-alart"
            }
        }]
    }'

コンソールでも確認しておきます。
問題なく作成されてますね。
image4

IoT Coreのルールでは転送先のCloudWatchメトリクスのディメンションは指定できません。
なので、次に作成するCloudWatchメトリクスではディメンションはなし(None)にしておきます。

CloudWatch

CloudWatch メトリクス

最初にIoT Coreからデータを受け取るCloudWatchメトリクスを作成します。
image5

以下のパラメータで作成します。

パラメータ
名前空間 IoT/Device
aws cloudwatch put-metric-data \
    --region ap-northeast-1 \
    --namespace "IoT/Device" \
    --value 0

CloudWatchメトリクスに新しいカスタム名前空間が作成されているのが分かりますね。
image6

CloudWatch アラーム

先ほど作成したメトリクスに対してアラームを設定します。
image7

SNS トピック

アラームを作る前にアラート発行時にメールを通知するためのSNSトピックを作成しておきます。

aws sns create-topic --name demo-topic-alart --region ap-northeast-1

#以下はレスポンス
{
    "TopicArn": "arn:aws:sns:ap-northeast-1:<account-id>:demo-topic-alart"
}

レスポンスのARNを控えておきましょう。

次にトピックをサブスクライブするメールアドレスを設定します。
トピック作成時のレスポンスのARNとサブスクライブするメールアドレスを入力します。

aws sns subscribe --topic-arn <トピックのARN> \
    --region ap-northeast-1 \
    --protocol email \
    --notification-endpoint \
    <your-email>@example.com 

設定したメールアドレス宛に検証メールが届くので、「Confirm subscription」をクリックします。
image8

これでSNSの設定は完了です。

しきい値を超えた場合のアラーム

今回はtempの値が30.0を超えた場合にアラートを発行したいと思います。
以下のパラメータで作成していきます。

パラメータ
アラーム名 temp-threshold
名前空間 IoT/Device
メトリクス名 temp
期間 60
評価期間 1
しきい値 30.0
統計 最大値
比較演算子 しきい値より大きい
欠落データの扱い 無視
通知 異常時、正常に回復した時
aws cloudwatch put-metric-alarm \
    --region ap-northeast-1 \
    --alarm-name "temp-threshold" \
    --namespace "IoT/Device" \
    --metric-name "temp" \
    --period 60 \
    --evaluation-periods 1 \
    --threshold 30.0 \
    --statistic Maximum \
    --comparison-operator GreaterThanThreshold \
    --treat-missing-data ignore \
    --alarm-actions arn:aws:sns:ap-northeast-1:<account-id>:demo-topic-alart \
    --ok-actions arn:aws:sns:ap-northeast-1:<account-id>:demo-topic-alart

しきい値を下回った場合のアラーム設定の肝は --ok-actions オプションです。
--ok-actions はコンソール画面だと画像の箇所です。
image9

--ok-actions とすることで状態が変化(回復)した場合にも通知が発行されます。
こちらのブログでも紹介されています。
https://dev.classmethod.jp/articles/tsnote-cloudwatch-alarm-ok-alarm-insuffientdata-actions/

コンソール画面でも確認しておきます。
新しいアラームが作成されていますね。
image10

動作確認

それでは実際にデータを入れてアラートの発報を確認してみます。

まずは正常な状態を確認するためにtempが30.0以下のデータを入れてみます。
以下のようなテストデータをIoT Coreのテストクライアントでいくつか発行して正常な状態を確認します。

{
  "deviceid": "a1234",
  "temp": 22.3
}

image11

CloudWatch側でメトリクスを取得していることを確認します。
正常値としてデータが記録されていますね。
image12

それでは同じ要領で30.0を超える値を入れてみましょう。
少し待つとアラームが発行されました。
image13

アラームを確認してみます。
想定通り、30.0を超えたことでアラーム状態になっています。
image14

また、アラートに連動してメールも通知されています。
image15

では、次は30.0以下のデータを入れてアラートが消え、回復通知が発報されるとことを確認してみます。
(データを入れるタイミングが遅かったので、少し見ずらいですが10:03~04のあたりですね)
image16

左側のアラームの部分が回復しているのがわかりますね。
メールでもアラートが解除された旨が通知されています。
image17

これで一通りの仕組み作りは完了です!

削除

最後に、検証で使用した各リソースを削除しておきます。

$ aws iam delete-role-policy --role-name demo-role-iot-rule-alart --policy-name demo-inline-policy-iot-rule-alart
$ aws iam delete-role --role-name demo-role-iot-rule-alart
$ aws iot delete-topic-rule --rule-name demo_iot_rule_temp_monitor
$ aws sns delete-topic --topic-arn arn:aws:sns:ap-northeast-1:<accout-id>:demo-topic-alart
$ aws cloudwatch delete-alarms --alarm-names temp-threshold

ちなみに、カスタムメトリクスは手動で削除できません。
https://dev.classmethod.jp/articles/tsnote-support-cloudwatch-delete-metrics-launch-001/

まとめ

IoT Coreで受け取ったデータをCloudWatchに流してアラート発砲〜アラート解除までの流れを作成してみました。
あまり細かいカスタマイズはできませんが、簡単なしきい値ベースのアラート通知であればすぐに実装できることがわかりました。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.